package com.example.lib_network.viewmodel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.lib_framework.log.LogUtil
import com.example.lib_network.baseBean.BaseResponse
import com.example.lib_network.callback.ApiErroCallBack
import com.example.lib_network.error.ApiException
import com.example.lib_network.error.ERROR
import com.example.lib_network.error.ExceptionHandler
import com.example.lib_network.flow.requestFlow
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout

/**
 *
 * @Description TODO
 * @Author Bohemian
 * @CreateTime 2024/01/19/ 20:33
 */
open class BaseViewModel:ViewModel(){
    fun launchUI(errorBlock:(Int?,String?)->Unit,response: suspend ()->Unit){
        viewModelScope.launch(Dispatchers.Main) {
            safeApiCall(errorBlock,response)
        }
    }
    suspend fun <T> safeApiCall(errorBlock: suspend (Int?, String?) -> Unit,response: suspend ()->T?):T?{
        try {
            return response()
        }catch (e:Exception)
        {
            e.printStackTrace()
            LogUtil.e(e)
            val handlerException = ExceptionHandler.handlerException(e)
            errorBlock(handlerException.errCode,handlerException.errMsg)
        }
        return null
    }

    fun <T> launchUIWithResult(responseBlock:suspend ()->BaseResponse<T>?,errocall: ApiErroCallBack?,successBlock:(T?)->Unit){
        viewModelScope.launch(Dispatchers.Main){
            safeApiCallWithResult(errocall,responseBlock)
        }
    }
    suspend fun <T>safeApiCallWithResult(errocall: ApiErroCallBack?,
                                         responseBlock: suspend ()->BaseResponse<T>?):T?{
        try {
                val response=withContext(Dispatchers.IO){
                    withTimeout(10*1000){
                        responseBlock()
                    }
                }?:return null
            if(response.isFailed())
            {
                throw ApiException(response.erroCode, response.erroMsg)
            }
            return response.data
        }catch (e:Exception){
            e.printStackTrace()
            LogUtil.e(e)
            val handlerException = ExceptionHandler.handlerException(e)
            errocall?.onErro(handlerException.errCode,  handlerException.message)
        }
        return null
    }
    fun <T>launchFlow(errocall: ApiErroCallBack?=null,
                      requestCall:suspend ()->BaseResponse<T>?,
                      showloading:((Boolean)->Unit)?=null,
                      successBlock:(T?)->Unit){
            val data=viewModelScope.launch(Dispatchers.Main){
                val data=requestFlow(errorBlock = {code,msg->
                    errocall?.onErro(code,msg)
                },requestCall,showloading)
                successBlock(data)
            }
    }
}